package online_store.controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringWriter;
import java.sql.Blob;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.sql.rowset.serial.SerialBlob;

import online_store.model.bus.CategoryBus;
import online_store.model.bus.ProductBus;
import online_store.model.bus.UserBus;
import online_store.model.dto.CategoryDTO;
import online_store.model.dto.ProductDTO;
import online_store.model.dto.UserDTO;
import online_store.utils.Constants;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;


@Controller
public class SpringController {

	@Autowired
	private UserBus userBus;
	
	@Autowired
	private CategoryBus categoryBus;
	
	@Autowired
	private ProductBus productBus;
	
	@RequestMapping(value="/user/login", method=RequestMethod.POST)
	public void login(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException{
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String loginkeeping = request.getParameter("loginkeeping");
		
		String errorMessage = "";
		
		UserDTO user = userBus.findByUser_Pass(username, password);
		if(user == null){
			errorMessage = "?loginErrorMessage=invalid-username-password";
		}
		
		if(errorMessage.isEmpty()){ //login successful
			HttpSession session = request.getSession();
			session.setAttribute("user_id", user.getId());
			session.setAttribute("username", user.getUsername());
			
			//store data on cookie
			if(loginkeeping != null && loginkeeping.equals("true")){
				Cookie userIdCookie = new Cookie(Constants.ONLINE_STORE_USERID, user.getId() + "");
				Cookie usernameCookie = new Cookie(Constants.ONLINE_STORE_USERNAME, user.getUsername());
				
				userIdCookie.setMaxAge(1000 * 60 * 60);
				usernameCookie.setMaxAge(1000 * 60 * 60); //1 hour
				
				userIdCookie.setPath(request.getContextPath() + "/");
				usernameCookie.setPath(request.getContextPath() + "/");
				
				response.addCookie(usernameCookie);
				response.addCookie(userIdCookie);
			}
			
			response.sendRedirect(request.getContextPath() + "/index.jsp");
		}else{
			response.sendRedirect(request.getContextPath() + "/user/login.jsp" + errorMessage + "#tologin");
		}
		
	}
	
	@RequestMapping(value="/user/register", method=RequestMethod.POST)
	public void register(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException{
		UserDTO user = new UserDTO();
		user.setUsername(request.getParameter("usernamesignup"));
		user.setPassword(request.getParameter("passwordsignup"));
		user.setEmail(request.getParameter("emailsignup"));
		
		String errorMessage = "";
		int rs = userBus.createUser(user);
		if(rs == -1){
			errorMessage = "?regiterErrorMessage=duplicated-username";
		}
		
		if(errorMessage.equals("")){
			HttpSession session = request.getSession();
			session.setAttribute("user_id", user.getId());
			session.setAttribute("username", user.getUsername());
			
			response.sendRedirect(request.getContextPath() + "/index.jsp");
		}else{
			response.sendRedirect("login.jsp" + errorMessage + "#toregister");
		}
	}
	
	@RequestMapping(value="/logout", method=RequestMethod.GET)
	public String logout(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException{
		
		HttpSession session = request.getSession();
		session.invalidate();
		return "index";
	}
	

	@RequestMapping(value="/user/userDetail", method=RequestMethod.GET)
	public String userDetail(Model model, HttpSession session){
		String username = (String) session.getAttribute("username");
		UserDTO user = userBus.findByUsername(username);
		
		model.addAttribute("userDTO", user);
		return "user/userDetail";
	}
	
	@RequestMapping(value="/user/updateUser", method=RequestMethod.POST)
	public String updateUser(Model model, HttpSession session
			, HttpServletRequest request, HttpServletResponse response) throws IOException{
		System.out.println("asdasd " + session.getAttribute("user_id"));
		
		int user_id = (int) session.getAttribute("user_id");
		
		String changePass = request.getParameter("change_password");
		
		System.out.println("changePass : " + changePass);
		 
		UserDTO user = new UserDTO();
		user.setUsername(request.getParameter("username"));
		user.setEmail(request.getParameter("email"));
		if(changePass != null && changePass.equals("true")){
			user.setOldPass(request.getParameter("current_password"));
			user.setNewPass(request.getParameter("new_password"));
		}
		
		String errorMessage = "";
		int rs = userBus.updateUser(user_id, user);
		
		if(rs == -1){
			errorMessage = "?errorMessage=duplicated-username";
		}else if(rs == -2){
			errorMessage = "?errorMessage=invalid-current-password";
		}
		
		if(errorMessage.equals("")){
			session.setAttribute("user_id", user.getId());
			session.setAttribute("username", user.getUsername());
		}
//		response.sendRedirect(request.getContextPath() + "/user/userDetail" + errorMessage);
		
		model.addAttribute("userDTO", userBus.getUser(user_id));
		
		return "user/userDetail";
	}
	
	@RequestMapping(value = "/product/addCategory", method = RequestMethod.POST)
	public String addCategory(Model model, @RequestParam("category_name") String categoryName){
		CategoryDTO category = new CategoryDTO();
		category.setName(categoryName);
		
		int rs = categoryBus.createCategory(category);
		if(rs == -1){
			model.addAttribute("errorMessage", "duplicated-name");
		}else{
			model.addAttribute("successMessage", "successfully");
		}
		return "product/addCategory";
	}
	
	@RequestMapping(value="/product/getAddProductForm", method=RequestMethod.GET)
	public String getAddProductForm(Model model){
		model.addAttribute("category_list", categoryBus.findAll());

		return "product/addProduct";
	}
	
	@RequestMapping(value="/product/getEditProductForm", method=RequestMethod.GET)
	public String getUpdateProductForm(Model model, @RequestParam(value="product_id") String productId){
		ProductDTO product = productBus.getProduct(Integer.parseInt(productId));
		model.addAttribute("productDTO", product);
		model.addAttribute("category_list", categoryBus.findAll());

		return "product/updateProduct";
	}
	
	@RequestMapping(value = "/product/addProduct", method = RequestMethod.POST)
	public String addProduct(Model model, HttpServletRequest request){
		
		ProductDTO product = new ProductDTO();
		
		//process only if its multipart content
		if(ServletFileUpload.isMultipartContent(request)){
			try{
				DiskFileItemFactory factory = new DiskFileItemFactory();
				List<FileItem> multipart = new ServletFileUpload(factory).parseRequest(request);
				
				for(FileItem item : multipart){
					if(!item.isFormField()){
						String fileName = new File(item.getName()).getName();
						item.write(new File(request.getServletContext().getRealPath("/") + "product_image" + File.separator + fileName));
						product.setImage(fileName);
						
					}else{
						if(item.getFieldName().equals("name")){
							product.setName(item.getString());
						}else if(item.getFieldName().equals("desc")){
							product.setDesc(item.getString());
						}else if(item.getFieldName().equals("price")){
							product.setPrice(Double.parseDouble(item.getString()));
						}else if(item.getFieldName().equals("category")){
							product.setCategory_id(Integer.parseInt(item.getString()));
						}
					}
				}
			}catch(Exception e){
				System.out.println("Upload File Unsuccessfully!");
				e.printStackTrace();
			}
		}else{
			System.out.println("Sorry this Servlet only handles file upload request!");
		}
		product.setLast_update(new Date());
				
		int rs = productBus.createProduct(product);
		if(rs == -1){
			model.addAttribute("errorMessage", Constants.FAILER_ACTION + "Duplicated name.");
		}else{
			model.addAttribute("successMessage", Constants.SUCCESS_ACTION);
		}
		model.addAttribute("category_list", categoryBus.findAll());
		
		return "product/addProduct";
	}
	
	@RequestMapping(value = "/product/updateProduct", method = RequestMethod.POST)
	public String updateProduct(Model model, HttpServletRequest request){
		ProductDTO product = new ProductDTO();
		String changeImage = "true";
		String preImage = "";
		
		//process only if its multipart content
		if(ServletFileUpload.isMultipartContent(request)){
			try{
				DiskFileItemFactory factory = new DiskFileItemFactory();
				List<FileItem> multipart = new ServletFileUpload(factory).parseRequest(request);
				
				for(FileItem item : multipart){
					if(item.isFormField()){
						if(item.getFieldName().equals("resourcePrimKey")){
							product.setProduct_id(Integer.parseInt(item.getString()));
						}else if(item.getFieldName().equals("name")){
							product.setName(item.getString());
						}else if(item.getFieldName().equals("desc")){
							product.setDesc(item.getString());
						}else if(item.getFieldName().equals("price")){
							product.setPrice(Double.parseDouble(item.getString()));
						}else if(item.getFieldName().equals("category")){
							product.setCategory_id(Integer.parseInt(item.getString()));
						}else if(item.getFieldName().equals("change_image")){
							
							System.out.println("change_image : " + item.getString());
							
							if(item.getString() != null && item.getString().equals("true")){
								changeImage = "false";
							}
						}else if(item.getFieldName().equals("preImage")){
							preImage = item.getString();
						}
					}
				}
				if(changeImage.equals("true")){
					for(FileItem item : multipart){
						if(!item.isFormField()){
							String fileName = new File(item.getName()).getName();
							item.write(new File(Constants.UPLOAD_DIRECTORY + File.separator + fileName));
							product.setImage(fileName);
						}
					}
				}else{
					product.setImage(preImage);
				}
			}catch(Exception e){
				System.out.println("Upload File Unsuccessfully!");
				e.printStackTrace();
			}
		}else{
			System.out.println("Sorry this Servlet only handles file upload request!");
		}
		product.setLast_update(new Date());
				
		int rs = productBus.updateProduct(product);
		if(rs == -1){
			model.addAttribute("errorMessage", Constants.FAILER_ACTION + "Duplicated name.");
		}else{
			model.addAttribute("successMessage", Constants.SUCCESS_ACTION);
		}
		model.addAttribute("productDTO", product);
		model.addAttribute("category_list", categoryBus.findAll());
		
		return "product/updateProduct";
	}
	
	@RequestMapping(value="/product/searchProduct", method=RequestMethod.GET)
	public String getProducts(Model model){
		List<ProductDTO> list = productBus.findAll();
		model.addAttribute("product_list", list);
		
		return "product/searchProduct";
	}
	
	@RequestMapping(value="/product/deleteProduct", method=RequestMethod.GET)
	public String deleteProduct(Model model, @RequestParam(value="product_id") String productId){
		productBus.deleteProduct(Integer.parseInt(productId));
		List<ProductDTO> list = productBus.findAll();
		model.addAttribute("product_list", list);
		
		return "product/searchProduct";
	}
	
	@RequestMapping(value="/index.jsp", method=RequestMethod.GET)
	public String getIndex(Model model){
		     
		System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
		
		List<ProductDTO> list = productBus.findAll();
		model.addAttribute("product_list", list);
		
		return "index";
	}
	
	@RequestMapping(value="/test", method=RequestMethod.GET)
	public String test(Model model){
		
		System.out.println("xxxxxxxxxxxxxxxxxxxxxxxxxxxx");
		
		model.addAttribute("test", "aaaaaa");
		
		return "test";
		
	}
	
}
